Feat/qpay - #977
Conversation
Adds operator/recovery-gated promo pricing (SetPromoRate/RemovePromoRate/ChangeOperator/GetPromoRate), ported and adapted from profitphil/qubic-x402 PR #3 after a security review of the access-control and rate-bound logic. Discounted rates are clamped to [0.25%, 0.75%] and can never exceed the standard fee. Adds matching GoogleTest coverage for the new procedures.
Adds affiliateRegistrarId-gated referral links (SetAffiliate/RemoveAffiliate/ChangeAffiliateRegistrar/GetAffiliate), ported and adapted from profitphil/qubic-x402 PR #3 after a security review. A referrer earns 5% of a referred seller's fee for 52 epochs (~1 year), taken out of the fee (never the seller's net or buyer's payment). Self-referral is blocked, first-attribution-wins, and the link expires/purges the same way receipts do. affiliateRegistrarId is a separate admin role from operatorId so a compromised key only ever touches one surface; recoveryId can reassign either. Adds matching GoogleTest coverage.
88d5b0f to
dd83c14
Compare
|
Please let us know when this PR is ready for review. Also please add a description of the PR before that. |
https://github.com/profitphil/Proposal-deploy-QPAY-smart-contract |
Thanks, short notice the link at the end goes 404: https://github.com/profitphil/qubic-x402 |
invited you. plz check again |
|
Sadly the test suits runs into some errors on my machine: Please double check on your side. |
Three ContractQPayhub tests failed due to fixture bugs, not contract bugs;
src/contracts/QPayhub.h is unchanged.
EndEpochDistributesFeePoolAboveReserveToSharesAndTokenHolders funded the
QPAY issuer with 10,000,000 QU while QX charges 1,000,000,000 QU to issue
an asset, so IssueAsset refunded and issued nothing, leaving no token
holders for the 90% split. Fund from qxFees instead of a hardcoded amount.
NotifyQuUsdPriceReply{Valid,Invalid}ResolvedReply seeded
broadcastedComputors from computorPublicKeys, which holds only one entry
(sized by computorSeeds). Indices 1..675 read out of bounds, so nearly
every computor mapped to the same computorIndex(), all 676 commits
collapsed onto one slot, quorum (451) was never reached and the query
stayed PENDING with no reply to fetch. Use distinct synthetic keys and
init the engine from them, matching OracleEngineTest.
All 53 ContractQPayhub tests pass.
fixed it |
fnordspace
left a comment
There was a problem hiding this comment.
From a formal point of view the contract seems fine for me. Please note that we do not review the logic of the contract as part of the core team.
I annotated two things that I think are worth double checking, in particular also because I did not find test results for the oracle operation in the provided repo. (Maybe just did not find it or I was on the wrong branch).
Also I did not see any qpi.burn() in the contract, maybe I missed the note about the economic model but at the moment the contract reserve is not refilled and might run out after a moment.
I would highly suggest to have a proper external code review besides AI and a Security Audit as this is a payment system!
| // of the file - the same pattern TestExampleC.h uses. | ||
| using namespace Ch; | ||
| locals.query.currency1 = id(Q, U, B, I, C); | ||
| locals.query.currency2 = id(U, S, D, T); |
There was a problem hiding this comment.
Not sure if that works reliably. It would be saver to change to id(U, S, D, T, null);. See TestExampleC.h
| // rejection path. | ||
| PUBLIC_PROCEDURE_WITH_LOCALS(SubscribeToPriceFeed) | ||
| { | ||
| if (state.get().priceOracleSubscriptionId >= 0) |
There was a problem hiding this comment.
I suspect this will work for one epoch and then you can't re-subscribe with this guard present as priceOracleSubscriptionId = 0 after initial subscription and is not reset during epoch change.
No description provided.